From: Feng Wu Date: Tue, 17 Nov 2015 12:21:33 +0000 (+0100) Subject: x86: add cmpxchg16b support X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~2247 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=e0116acbbd0b18f395b56f589e0f0f8fcc6fc2e0;p=xen.git x86: add cmpxchg16b support This patch adds cmpxchg16b support for x86-64, so software can perform 128-bit atomic write/read. Signed-off-by: Feng Wu Reviewed-by: Jan Beulich --- diff --git a/xen/include/asm-x86/x86_64/system.h b/xen/include/asm-x86/x86_64/system.h index 662813ad8c..7026c05a25 100644 --- a/xen/include/asm-x86/x86_64/system.h +++ b/xen/include/asm-x86/x86_64/system.h @@ -5,6 +5,39 @@ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \ (unsigned long)(n),sizeof(*(ptr)))) +/* + * Atomic 16 bytes compare and exchange. Compare OLD with MEM, if + * identical, store NEW in MEM. Return the initial value in MEM. + * Success is indicated by comparing RETURN with OLD. + * + * This function can only be called when cpu_has_cx16 is true. + */ + +static always_inline __uint128_t __cmpxchg16b( + volatile void *ptr, const __uint128_t *old, const __uint128_t *new) +{ + __uint128_t prev; + uint64_t new_high = *new >> 64; + uint64_t new_low = *new; + + ASSERT(cpu_has_cx16); + + asm volatile ( "lock; cmpxchg16b %1" + : "=A" (prev), "+m" (*__xg(ptr)) + : "c" (new_high), "b" (new_low), + "0" (*old) ); + + return prev; +} + +#define cmpxchg16b(ptr, o, n) ({ \ + volatile void *_p = (ptr); \ + ASSERT(!((unsigned long)_p & 0xf)); \ + BUILD_BUG_ON(sizeof(*(o)) != sizeof(__uint128_t)); \ + BUILD_BUG_ON(sizeof(*(n)) != sizeof(__uint128_t)); \ + __cmpxchg16b(_p, (void *)(o), (void *)(n)); \ +}) + /* * This function causes value _o to be changed to _n at location _p. * If this access causes a fault then we return 1, otherwise we return 0.